package im

import (
	"fmt"
	"time"
	"strings"
	"errors"
	"dhfshop/models"
	"dhfshop/models/consts"
	//"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
)

// 发送模板消息需要的表单ID
type FormIdCache struct {
	FormIdCacheId   int64     `orm:"column(formid_cache_id);pk;auto" json:"formid_cache_id" form:"-"` //自增ID
	PartnerId       int64     `orm:"column(partner_id);index" json:"partner_id" form:"-"`        //组织ID
    MemberId        int64     `orm:"column(member_id);index" json:"member_id" form:"-"`          //
	AppId           string    `orm:"column(app_id);size(32)" json:"app_id" form:"app_id"`
	FormId          string    `orm:"column(form_id)" json:"form_id" form:"form_id"` 
	OpenId          string    `orm:"column(open_id)" json:"open_id" form:"-"`                    //接收者open_id
	Types           string    `orm:"column(types)" json:"types" form:"types"`                    //关联单据类型:order订单，yuyue预约单等
	Xid             string    `orm:"column(xid)" json:"xid" form:"xid"`                          //关联单据编号
	MaxCount        int       `orm:"column(max_count);default(1)" json:"max_count"`              //最大可使用次数
	CurUseCount     int       `orm:"column(cur_use_count);default(0)" json:"cur_use_count"`      //当前使用次数
	CreatedAt       time.Time `orm:"auto_now_add;column(created_at);type(datetime)" json:"-"`
	ExpireAt        time.Time `orm:"column(expire_at);type(datetime)" json:"-"`                  //过期时间，客服点击表单的时间+7天   
	// 非数据库字段
	CreatedAtStr    string    `orm:"-" json:"created_at"`
    ExpireAtStr   string    `orm:"-" json:"expire_at"`
}

func init() {
	orm.RegisterModel(new(FormIdCache))
}

func AddFormIdCache(m *FormIdCache) (id int64, err error) {
	o := models.GetDefaultDB()
	id, err = o.Insert(m)
	return id, err
}

func GetFormIdCacheById(id int64) (v *FormIdCache, err error) {
	o := models.GetDefaultDB()
	v = &FormIdCache{FormIdCacheId: id}
	if err = o.Read(v); err == nil {
		v.CreatedAtStr = v.CreatedAt.Format(consts.DATETIME_FORMAT)
        v.ExpireAtStr = v.ExpireAt.Format(consts.DATETIME_FORMAT)
		return v, nil
	}
	return nil, err
}

func GetAllFormIdCaches(query map[string]string,fields []string,order_by map[string]string,offset int,limit int)([]*FormIdCache,int64,error){
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(FormIdCache))
	for k, v := range query {
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	cnt, err := qs.Count()
	// order by:
	var sortFields []string
	for k, v := range order_by {
		orderby := ""
		if v == "desc" {
			orderby = "-" + k
		} else if v == "asc" {
			orderby = k
		} else {
			return nil, 0, errors.New("Error: Invalid order. Must be either [asc|desc]")
		}
		sortFields = append(sortFields, orderby)
	}
	qs = qs.OrderBy(sortFields...)
	var lists []*FormIdCache
	if _, err = qs.Limit(limit, offset).All(&lists, fields...); err == nil {
	    for _, formid := range lists {
			formid.CreatedAtStr = formid.CreatedAt.Format(consts.DATETIME_FORMAT)
            formid.ExpireAtStr = formid.ExpireAt.Format(consts.DATETIME_FORMAT)
	    }
		return lists, cnt, nil
	}
	return nil, 0, err
}

func UpdateFormIdCacheById(m *FormIdCache,param ... string) (err error) {
	o := models.GetDefaultDB()
	v := FormIdCache{FormIdCacheId: m.FormIdCacheId}
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Update(m, param...); err == nil {
			fmt.Println("Number of records updated in database:", num)
		}
	}
	return
}
func DeleteFormIdCache(id int64) (err error) {
	o := models.GetDefaultDB()
	v := FormIdCache{FormIdCacheId: id}
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&v); err == nil {
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}

func GetFormIdByOpenId(openId, types, xid string) (formId string, err error) {
	curUtcTime := time.Now().UTC()
	idCache := &FormIdCache{}
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(FormIdCache))
    qs = qs.Filter("open_id", openId)
	qs = qs.Filter("types", types)
	qs = qs.Filter("xid", xid)
	qs = qs.Filter("expire_at__gt", curUtcTime)
	if err = qs.One(idCache); err == nil {
		formId = idCache.FormId
		idCache.CurUseCount++
		o.Update(idCache, "cur_use_count")
		if idCache.CurUseCount >= idCache.MaxCount {
		    o.Delete(idCache)
		}
	}
	return
}

func GetValidFormId(OpenIdUserId map[string]int64, types string)(idCache *FormIdCache, err error) {
	idCache = &FormIdCache{}
	curUtcTime := time.Now().UTC()
	openIds :=[]string{}
	for key, _:= range OpenIdUserId {
	    openIds = append(openIds, key)
	}
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(FormIdCache))
    qs = qs.Filter("open_id__in", openIds)
	/*
	if len(openIds) > 1 {
	   qs = qs.Filter("open_id__in", openIds)
	} else {
	   qs = qs.Filter("open_id", openIds[0])
	}
	*/
	qs = qs.Filter("types", types)
	qs = qs.Filter("expire_at__gt", curUtcTime).OrderBy("expire_at")
	if err = qs.One(idCache); err == nil {
	    idCache.CurUseCount++
		o.Update(idCache, "cur_use_count")
		if idCache.CurUseCount >= idCache.MaxCount {
		    o.Delete(idCache)
		}
	}
	return
}

func ClearExpired() (err error) {
	o := models.GetDefaultDB()
	curTime := time.Now().UTC()
	if exist := o.QueryTable(new(FormIdCache)).Filter("expire_at__lte", curTime).Exist(); exist {
	    _, err = o.QueryTable(new(FormIdCache)).Filter("expire_at__lte", curTime).Delete()
	}
	return
}
